from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_ollama import ChatOllama
from service.rag_service import qa


class Qwen3Model:
    def __init__(self, chat_history=None):
        if chat_history is None:
            chat_history = []
        self.chat_history = chat_history

        # 初始化模型
        self.llm = ChatOllama(
            model="qwen3:1.7b",
            base_url="http://localhost:11434"
        )

        prompt="""
        你是一个嵌入在智能系统中的自然语言对话数字人，不仅能帮助用户查找信息，还能以得体、专业的方式与用户进行自然、流畅的交流。

        你具备以下三项核心能力：
        
        1.回答用户问题：当用户提出问题时，你应优先从提供的文本片段中寻找答案，准确引用和解释信息；
        
        2.知识补充：如果文本中没有答案，你可以基于自己的知识和常识进行补充，确保回答真实、有帮助；
        
        3.正式交流：当用户表达观点或进行日常交流时，你应以自然、礼貌且正式的方式回应，避免俚语或过度口语化表达，保持专业风格。
        
        请按照以下要求执行任务：
        
        (C) 上下文：你会接收用户的输入（可能是问题、也可能是聊天内容），系统同时会提供一段或多段参考文本。你需判断用户意图，是在提问还是在交流，并作出相应回应。
        
        (O) 目标：理解用户意图，选择恰当的应答策略：
        
        如果是提问，就从文本中找信息；
        
        如果没有答案，可以用你自己的知识回答；
        
        如果是非正式交流，也请使用规范、礼貌的语言回应，并保持逻辑清晰。
        
        (S) 风格：风格应保持正式、清晰、得体：
        
        解答问题时保持结构完整、术语准确；
        
        交流时语言自然但不随意；
        
        避免使用网络俚语、缩略口语或夸张语气。
        
        (T) 语气：语气应温和、礼貌、专业。
        
        可适度使用自然语气词（如“是的”、“当然”、“确实”等）以增强亲和力；
        
        严禁使用表情符号（如“🙂”）或颜文字（如“╯︿╰”）；
        
        禁止使用口头语（如“哈”、“哇”、“嘿嘿”）或网络流行表达。
        
        (A) 受众：用户可能是普通用户或企业用户，他们可能希望获取信息，也可能需要简短交流。请确保用语规范、清晰、通俗易懂，避免过度技术化或非正式表达。
        
        (R) 响应格式：
        
        使用完整的自然语言段落；
        
        如果引用文本内容，请用引号标注；
        
        如文本未提及相关信息，可使用通用知识补充；
        
        如用户是交流状态，请以正式且自然的语气回应；
        
        严禁使用表情符号或颜文字；
        
        所有回答须以文字为主，结构清晰、语言规范。
        
        现在，请根据以下输入开始对话：
        【用户输入】：{{用户的消息或问题}}
        【参考文本片段】：{text}

        """

        # 定义 prompt 模板
        self.prompt = ChatPromptTemplate.from_messages([
            ("system", prompt),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{question}")
        ])

        # 组合链：prompt + 模型
        self.chain = self.prompt | self.llm

    async def chat(self, question: str):
        try:
            text = await qa(question)
            # 构造上下文历史消息
            messages = []
            for content in self.chat_history:
                # 添加格式校验
                if not isinstance(content, dict) or 'type' not in content or 'content' not in content:
                    print(f"Invalid chat history format: {content}")
                    continue

                content_type = content.get('type')
                content_value = content.get('content')

                # 验证 content 是否为有效字符串
                if not isinstance(content_value, str):
                    print(f"Invalid content value: {content_value}")
                    continue

                if content_type == "human":
                    messages.append(HumanMessage(content=content_value).model_dump_json(include={
                        "type",
                        "content"
                    }))
                elif content_type == "ai":
                    messages.append(AIMessage(content=content_value).model_dump_json(include={
                        "type",
                        "content"
                    }))
            # 执行链
            response = self.chain.invoke({  # 使用 await 获取实际结果
                "chat_history": messages,
                "question": question,
                "text": text
            })

            answer = response.content
            # 更新历史记录
            self.chat_history.append({"type": "human", "content": question})
            self.chat_history.append({"type": "ai", "content": answer})
            return answer
        except Exception as e:
            print(f"对话出错: {e}")
            return None